home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / hdutil.arc / OWNER.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-08-22  |  27.0 KB  |  632 lines

  1. PAGE ,132
  2. TITLE IBM-PC Cluster Owner Program, Version 1.40, 21-Aug-1986
  3.  
  4. ;
  5. ; Written By Steven Georgiades
  6. ;
  7. ; IBM-PC/XT Cluster Owner Program
  8. ;   Will respond with the name of the file that owns the specified cluster.
  9. ;
  10. ;       If you are using this program and find it of value, your
  11. ;       contribution in any amount ($5.00 suggested) will be greatly
  12. ;       appreciated.  Makes checks payable to Steven M. Georgiades.
  13. ;               Thank you.
  14. ;
  15. ;       If you have any questions or comments about this or any other
  16. ;       SMG program, call or write:
  17. ;
  18. ;               Steven M. Georgiades
  19. ;               701-H South Hayward Street
  20. ;               Anaheim, CA 92804
  21. ;               (714) 826-9549
  22. ;
  23.  
  24. CODE      SEGMENT BYTE PUBLIC 'CODE'
  25.  
  26.           ASSUME  CS:CODE,DS:CODE,ES:CODE,SS:CODE
  27.  
  28.           ORG     5CH
  29.  
  30. FCB       LABEL   BYTE
  31.  
  32.           ORG     80H
  33.  
  34. PARAM     LABEL   BYTE
  35.  
  36.           ORG     100H
  37.  
  38. OWNER:    JMP     BEGIN
  39.  
  40. CRLF      DB      13,10,"$"
  41. DIGIT     DB      "0123456789ABCDEF"
  42. READERR   DB      "Error Reading Drive X:",7,13,10,"$"
  43. SIGNON    DB      "Owner, Version 1.40",13,10,10,"$"
  44.  
  45. CLUSTMSG  DB      "Cluster XXXXX $"
  46. OWNERMSG  DB      "is Owned by $"
  47. BADMSG    DB      "is Marked as Bad",13,10,"$"
  48. FREEMSG   DB      "is not is Use by any File",13,10,"$"
  49. INVALID   DB      "does not Exist!",7,13,10,"$"
  50. LOSTMSG   DB      "Appears to be Lost!",7,13,10,"$"
  51. RESVMSG   DB      "is Reserved",13,10,"$"
  52.  
  53. CLSTSEC   DW      ?
  54. CLSTTOT   DW      ?
  55. CLUST     DW      ?
  56. DIR_LEN   DW      ?
  57. DIRBUF    DW      ?
  58. DIRSEC    DW      ?
  59. DRIVE     DB      ?
  60. EOF       DW      0FF8H
  61. FATSEC    DW      ?
  62. FATSIZE   DB      3
  63. RDIR_LEN  DW      ?
  64. SECSIZE   DW      ?
  65. STARTSEC  DW      ?
  66.  
  67. DIRNAME   DB      14 DUP(0)
  68. FILESPEC  DB      "X:\"
  69. PATH      DB      "$",79 DUP(0)
  70. FILENAME  DB      14 DUP(0)
  71.  
  72. BEGIN:    MOV     AH,9                          ; Output Sign-On Message
  73.           MOV     DX,OFFSET SIGNON
  74.           INT     21H
  75.           MOV     AH,19H                        ; Get Default Drive Number
  76.           INT     21H
  77.           MOV     DRIVE,AL                      ;   and Save
  78.           MOV     SI,OFFSET PARAM               ; Set up Pointer to Parameter
  79.           LODSB                                 ; Read Parameter Length
  80.           CBW
  81.           MOV     BX,AX
  82.           MOV     BYTE PTR [SI][BX],0           ; Terminate Parameter String
  83. STRIP:    LODSB                                 ; Strip Off Leading Whitespace
  84.           CMP     AL,' '
  85.           JE      STRIP
  86.           CMP     AL,9
  87.           JE      STRIP
  88.           OR      AL,AL                         ; If End-of-Parameter,
  89.           JZ      RD_BOOT                       ;   Continue Proccessing
  90.           CMP     AL,'/'                        ; If Switch, Process
  91.           JE      SWITCH
  92.           DEC     SI                            ; ReUse Last Character
  93.           CALL    GET_WORD                      ; Read Cluster Number (Hex)
  94.           MOV     CLUST,DX                      ; Save Cluster Number
  95.           JMP     SHORT STRIP                   ; Get Next Parameter
  96. SWITCH:   LODSB                                 ; Get Drive Letter
  97.           SUB     AL,'A'                        ; Convert to Drive Number 
  98.           MOV     DRIVE,AL                      ; Save Drive Number
  99.           JMP     SHORT STRIP                   ; Get Next Paramter
  100. RD_BOOT:  MOV     AL,DRIVE                      ; Read Boot Record
  101.           MOV     CX,1
  102.           MOV     DX,0
  103.           MOV     BX,OFFSET FATBUF
  104.           INT     25H
  105.           JNC     BOOT_OK
  106.           JMP     RDERROR                       ; If Error, Say So
  107. BOOT_OK:  POPF
  108.           MOV     AX,FATBUF[11]                 ; Read Sector Size
  109.           MOV     SECSIZE,AX                    ;   and Save
  110.           MOV     AL,BYTE PTR FATBUF[13]        ; Read Sectors per Cluster
  111.           XOR     AH,AH
  112.           MOV     CLSTSEC,AX                    ;   and Save
  113.           MOV     CX,FATBUF[14]                 ; Read # of Reserved Sectors
  114.           MOV     AL,BYTE PTR FATBUF[16]        ; Read # of FAT's
  115.           XOR     AH,AH                         ; Convert to Word
  116.           MOV     BX,FATBUF[22]                 ; Read Sectors per FAT
  117.           MOV     FATSEC,BX
  118.           MUL     BX                            ; Calculate Total FAT Sectors
  119.           ADD     CX,AX                         ; Add to Reserved Sectors
  120.           MOV     AX,FATBUF[17]                 ; Read Number of DIR Entries
  121.           MOV     RDIR_LEN,AX
  122.           PUSH    CX                            ; Calculate DIR Sectors
  123.           MOV     CL,5
  124.           SHL     AX,CL
  125.           POP     CX
  126.           MOV     BX,SECSIZE
  127.           XOR     DX,DX
  128.           DIV     BX
  129.           OR      DX,DX                         ; Adjust for Partial Sector
  130.           JZ      NO_ADD
  131.           INC     AX
  132. NO_ADD:   MOV     DIRSEC,AX                     ; Save DIR Sectors
  133.           ADD     CX,AX                         ; Add DIR Sectors to Reserved
  134.           MOV     STARTSEC,CX                   ; Save in STARTSEC
  135.           MOV     AX,FATSEC                     ; Determine FAT Buffer Size
  136.           MOV     BX,SECSIZE
  137.           MUL     BX
  138.           ADD     AX,OFFSET FATBUF
  139.           MOV     DIRBUF,AX                     ; Save DIRBUF Pointer
  140.           MOV     AX,FATBUF[19]                 ; Read Total Sectors on Media
  141.           SUB     AX,CX                         ; Calculate Total Data Clusters
  142.           MOV     BX,CLSTSEC
  143.           XOR     DX,DX
  144.           DIV     BX
  145.           ADD     AX,2
  146.           MOV     CLSTTOT,AX                    ;   and Save
  147.           CMP     AX,4081                       ; If Necessary, Adjust FAT Size
  148.           JLE     FAT_OK
  149.           MOV     FATSIZE,4
  150.           MOV     EOF,0FFF8H
  151. FAT_OK:   MOV     AL,DRIVE                      ; Read FAT
  152.           MOV     CX,FATSEC
  153.           MOV     DX,1
  154.           MOV     BX,OFFSET FATBUF
  155.           INT     25H
  156.           JC      RDERROR                       ; If Error, Say So
  157.           POPF
  158.           MOV     BX,CLUST                      ; Get Cluster Number
  159.           MOV     AX,BX                         ; Convert Cluster # to Decimal
  160.           MOV     DI,OFFSET CLUSTMSG[13]
  161.           CALL    DEC5OUT
  162.           CALL    STRIP0                        ; Strip Off Leading Zeroes
  163.           MOV     AH,9
  164.           MOV     DX,OFFSET CLUSTMSG            ; Output Cluster Message
  165.           INT     21H
  166.           CMP     BX,CLSTTOT                    ; Test Cluster Number
  167.           JNB     CLSTBAD
  168.           CMP     BX,2
  169.           JNB     CLST_OK
  170. CLSTBAD:  MOV     DX,OFFSET INVALID             ; If Invalid, Say So
  171.           JMP     SHORT ERROUT
  172. CLST_OK:  CALL    NEXTCLST                      ; Determine Next Cluster
  173.           OR      BX,BX                         ; If Not in Use, Say So
  174.           JNZ     NOT_FREE
  175.           MOV     DX,OFFSET FREEMSG
  176.           JMP     SHORT ERROUT
  177. NOT_FREE: MOV     AX,EOF                        ; If In Use, Continue
  178.           CMP     BX,AX
  179.           JAE     CLSTGOOD
  180.           DEC     AX                            ; If Bad, Say So
  181.           CMP     BX,AX
  182.           JNE     NOT_BAD
  183.           MOV     DX,OFFSET BADMSG
  184.           JMP     SHORT ERROUT
  185. NOT_BAD:  SUB     AX,7                          ; If Reserved, Say So
  186.           CMP     BX,AX
  187.           JB      CLSTGOOD
  188.           MOV     DX,OFFSET RESVMSG
  189. ERROUT:   MOV     AH,9                          ; Output Error Message
  190.           INT     21H
  191.           MOV     AX,4C01H                      ; Exit to DOS
  192.           INT     21H
  193. RDERROR:  POPF                                  ; Handle Read Error
  194.           MOV     AL,DRIVE
  195.           ADD     AL,'A'
  196.           MOV     READERR[20],AL
  197.           MOV     DX,OFFSET READERR
  198.           JMP     SHORT ERROUT
  199. CLSTGOOD: MOV     AX,CLUST                      ; Get Cluster Number
  200. CLSTBACK: MOV     BX,AX                         ; Get Previous Cluster in Chain
  201.           CALL    PREVCLST
  202.           OR      AX,AX                         ; If Not First, Repeat
  203.           JNZ     CLSTBACK
  204.           MOV     CLUST,BX                      ; Save First Cluster in Chain
  205. LOOKHERE: CALL    GETDIR                        ; Load the Current Directory
  206.           CALL    SRCHCLST                      ; Search Directory for Cluster
  207.           JNC     FOUND                         ; If Found, Exit Search Loop
  208.           CALL    SRCHDIR                       ; Search Dir for Sub-Directory
  209.           JNC     LOOKHERE                      ; If Found, Continue Search Loop
  210.           CALL    DIRNEXT                       ; Use Next Sub-Directory
  211.           JNC     LOOKHERE                      ; If Found, Continue Search Loop
  212.           MOV     DX,OFFSET LOSTMSG             ; Else Couldn't find Cluster
  213.           JMP     ERROUT
  214. FOUND:    MOV     AL,DRIVE                      ; Convert Drive Number to Letter
  215.           ADD     AL,'A'
  216.           MOV     FILESPEC,AL
  217.           MOV     AH,9                          ; Output Owner Message
  218.           MOV     DX,OFFSET OWNERMSG
  219.           INT     21H
  220.           MOV     DX,OFFSET FILESPEC            ; Output FileSpec
  221.           INT     21H
  222.           MOV     DX,OFFSET FILENAME            ; Output FileName
  223.           INT     21H
  224.           MOV     DX,OFFSET CRLF
  225.           INT     21H
  226. EXIT:     MOV     AX,4C00H                      ; Exit to DOS
  227.           INT     21H
  228.  
  229. DIRNEXT:  PUSH    AX                            ; Save Registers
  230.           PUSH    BX
  231.           PUSH    CX
  232.           PUSH    DI
  233.           PUSH    SI
  234. DIRNEXT1: MOV     DI,OFFSET PATH                ; Scan to End of Path
  235.           MOV     CX,80
  236.           MOV     AL,'$'
  237.           REPNE   SCASB
  238.           JNE     DIRNEXT3                      ; If No End, Error
  239.           CMP     CX,79                         ; If Null Path, Error
  240.           JE      DIRNEXT3
  241.           STD                                   ; Auto-Decrement
  242.           MOV     AX,78                         ; Determine Path Length
  243.           SUB     AX,CX
  244.           MOV     CX,AX
  245.           SUB     DI,2                          ; Point to End of DirName
  246.           MOV     AL,0                          ; Set End of DirName
  247.           STOSB
  248.           MOV     AL,'\'                        ; Scan to Previous DirName
  249.           REPNE   SCASB
  250.           JE      DIRNEXT2                      ; If Not Found,
  251.           MOV     DI,OFFSET PATH[-2]            ;   Point to Start of Path
  252. DIRNEXT2: CLD                                   ; Auto-Increment
  253.           ADD     DI,2                          ; Copy Last SubDir to FileName
  254.           PUSH    DI
  255.           MOV     SI,DI
  256.           MOV     DI,OFFSET FILENAME
  257.           CALL    MOVSTR
  258.           POP     DI
  259.           MOV     AL,'$'                        ; Terminate Path String
  260.           STOSB
  261.           CALL    GETDIR                        ; Read Directory
  262.           JC      DIRNEXT4                      ; If Error, Say So
  263.           MOV     SI,OFFSET FILENAME
  264.           MOV     DI,OFFSET DIRNAME
  265.           CALL    MOVSTR
  266.           CALL    SRCHFILE                      ; Search for FileName
  267.           JC      DIRNEXT4                      ; If Error, Say So
  268.           MOV     SI,BX                         ; Save Pointer
  269.           ADD     SI,32                         ; Point to Next Dir Entry
  270.           MOV     AX,SI                         ; Determine Dir Entry Count
  271.           SUB     AX,DIRBUF
  272.           MOV     CL,5
  273.           SHR     AX,CL
  274.           MOV     CX,DIR_LEN
  275.           SUB     CX,AX
  276.           CALL    FINDDIR                       ; Find Next SubDirectory
  277.           JC      DIRNEXT1
  278.           JMP     SHORT DIRNEXT4
  279. DIRNEXT3: STC                                   ; Set Error Return Flag
  280. DIRNEXT4: POP     SI                            ; Restore Registers
  281.           POP     DI
  282.           POP     CX
  283.           POP     BX
  284.           POP     AX
  285.           RET                                   ; Done
  286.  
  287. GETDIR:   PUSH    AX                            ; Save Registers
  288.           PUSH    BX
  289.           PUSH    CX
  290.           PUSH    DX
  291.           PUSH    DI
  292.           PUSH    SI
  293.           MOV     AL,DRIVE                      ; Read Root Directory
  294.           MOV     CX,DIRSEC
  295.           MOV     DX,STARTSEC
  296.           SUB     DX,CX
  297.           MOV     BX,DIRBUF
  298.           INT     25H
  299.           POPF
  300.           MOV     AX,RDIR_LEN                   ; DIR Length = Root DIR Length
  301.           MOV     DIR_LEN,AX
  302.           MOV     SI,OFFSET PATH                ; Point to First Element of Path
  303. GETDIR1:  MOV     DI,OFFSET DIRNAME             ; Point to FileName Buffer
  304. GETDIR2:  LODSB                                 ; Copy Path Element to FileName
  305.           CMP     AL,'\'                        ;   until '\' or '$'
  306.           JE      GETDIR3
  307.           CMP     AL,'$'
  308.           JE      GETDIR4
  309.           STOSB
  310.           JMP     SHORT GETDIR2
  311. GETDIR3:  MOV     AL,0                          ; Read Subdirectory
  312.           STOSB
  313.           CALL    READDIR
  314.           JC      GETDIR5                       ; If Error, Say So
  315.           JMP     SHORT GETDIR1                 ; Get Next Element
  316. GETDIR4:  CLC                                   ; Clear Error Flag
  317. GETDIR5:  POP     SI                            ; Restore Registers
  318.           POP     DI
  319.           POP     DX
  320.           POP     CX
  321.           POP     BX
  322.           POP     AX
  323.           RET                                   ; Done
  324.  
  325. READDIR:  PUSH    CX                            ; Save Registers
  326.           PUSH    DI
  327.           PUSH    SI
  328.           CALL    SRCHFILE                      ; Search for DIR
  329.           JC      READDIR2                      ; If Not Found, Error
  330.           MOV     BX,[BX+26]                    ; Get Starting Cluster Number
  331.           MOV     DIR_LEN,0                     ; DIR Length = 0
  332.           OR      BX,BX                         ; If Start Cluster = 0, Error
  333.           JZ      READDIR2
  334.           MOV     AX,SECSIZE                    ; Calculate DIR Entries/Cluster
  335.           MOV     CX,CLSTSEC
  336.           MUL     CX
  337.           MOV     CL,5
  338.           SHR     AX,CL
  339.           MOV     CX,AX
  340.           MOV     DI,DIRBUF                     ; Point to DIR Buffer
  341. READDIR1: CALL    READCLST                      ; Read Cluster
  342.           ADD     DIR_LEN,CX                    ; Increment DIR Length
  343.           CMP     BX,EOF                        ; If Not Last Cluster,
  344.           JB      READDIR1                      ;   Get Next Cluster
  345.           JMP     SHORT READDIR3                ; Done Reading DIR
  346. READDIR2: STC                                   ; Set Error Flag
  347. READDIR3: POP     SI                            ; Restore Registers
  348.           POP     DI
  349.           POP     CX
  350.           RET                                   ; Done
  351.  
  352. SRCHDIR:  PUSH    CX                            ; Save Registers
  353.           PUSH    SI
  354.           MOV     SI,DIRBUF                     ; Point to First DIR Entry
  355.           MOV     CX,DIR_LEN                    ; Load DIR Length
  356.           CALL    FINDDIR                       ; Find SubDirectory
  357.           POP     SI                            ; Restore Registers
  358.           POP     CX
  359.           RET                                   ; Done
  360.  
  361. FINDDIR:  PUSH    AX                            ; Save Registers
  362.           PUSH    DI
  363. FINDDIR1: JCXZ    FINDDIR4                      ; If Zero, Not Found
  364. FINDDIR2: CMP     BYTE PTR [SI],'.'             ; If '.' or '..', Skip
  365.           JE      FINDDIR3
  366.           CMP     BYTE PTR [SI],0E5H            ; If Deleted, Skip
  367.           JE      FINDDIR3
  368.           TEST    BYTE PTR [SI+11],10H          ; Test File Attribute
  369.           JNZ     FINDDIR5                      ; If Match, Found
  370. FINDDIR3: ADD     SI,32                         ; Else Next DIR Entry
  371.           LOOP    FINDDIR2                      ; and Repeat
  372. FINDDIR4: STC                                   ; Set Error Flag
  373.           JMP     SHORT FINDDIR6                ; Done
  374. FINDDIR5: MOV     DI,OFFSET DIRNAME
  375.           CALL    UNPARSE                       ; UnParse Directory Name
  376.           MOV     DI,OFFSET PATH                ; Search for End of Path
  377.           MOV     AL,'$'
  378.           MOV     CX,80
  379.           REPNE   SCASB
  380.           JNE     FINDDIR4                      ; If Not Found, Error
  381.           DEC     DI
  382.           MOV     BX,SI                         ; Set Pointer to DIR Entry
  383.           MOV     SI,OFFSET DIRNAME             ; Copy Directory Name to Path
  384.           CALL    MOVSTR
  385.           DEC     DI
  386.           MOV     AX,'$\'                       ; Terminate Path
  387.           STOSW
  388.           CLC                                   ; Clear Error Flag
  389. FINDDIR6: POP     DI                            ; Restore Registers
  390.           POP     AX
  391.           RET                                   ; Done
  392.  
  393. SRCHFILE: PUSH    AX                            ; Save Register
  394.           PUSH    CX
  395.           PUSH    DI
  396.           PUSH    SI
  397.           MOV     AX,2900H                      ; Parse Filename
  398.           MOV     SI,OFFSET DIRNAME
  399.           MOV     DI,OFFSET FCB
  400.           INT     21H
  401.           INC     DI                            ; Point to Filename in FCB
  402.           MOV     SI,DIRBUF                     ; Point to Start of DIRBUF
  403.           MOV     CX,DIR_LEN                    ; Load DIR Length
  404.           JCXZ    SRCHFIL2                      ; If Zero, Not Found
  405. SRCHFIL1: PUSH    CX                            ; Save Registers
  406.           PUSH    DI
  407.           PUSH    SI
  408.           MOV     CX,11                         ; Compare Filename
  409.           REPE    CMPSB
  410.           POP     SI                            ; Restore Registers
  411.           POP     DI
  412.           POP     CX
  413.           JE      SRCHFIL3                      ; If Match, Found
  414.           ADD     SI,32                         ; Else Next DIR Entry
  415.           LOOP    SRCHFIL1                      ; and Repeat
  416. SRCHFIL2: STC                                   ; Set Error Flag
  417.           JMP     SHORT SRCHFIL4                ; Done
  418. SRCHFIL3: MOV     BX,SI                         ; Set Pointer to DIR Entry
  419.           CLC                                   ; Clear Error Flag
  420. SRCHFIL4: POP     SI                            ; Restore Registers
  421.           POP     DI
  422.           POP     CX
  423.           POP     AX
  424.           RET                                   ; Done
  425.  
  426. SRCHCLST: PUSH    AX                            ; Save Register
  427.           PUSH    CX
  428.           PUSH    DI
  429.           PUSH    SI
  430.           MOV     SI,DIRBUF                     ; Point to First DIR Entry
  431.           MOV     CX,DIR_LEN                    ; Load DIR Length
  432.           JCXZ    SRCHCLS3                      ; If Zero, Not Found
  433.           MOV     BX,CLUST
  434. SRCHCLS1: CMP     BYTE PTR [SI],'.'             ; If '.' or '..', Skip
  435.           JE      SRCHCLS2
  436.           CMP     BYTE PTR [SI],0E5H            ; If Deleted, Skip
  437.           JE      SRCHCLS2
  438.           CMP     BX,[SI+26]                    ; Compare Start Cluster Number
  439.           JE      SRCHCLS4                      ; If Match, Found
  440. SRCHCLS2: ADD     SI,32                         ; Else Next DIR Entry
  441.           LOOP    SRCHCLS1                      ; and Repeat
  442. SRCHCLS3: STC                                   ; Set Error Flag
  443.           JMP     SHORT SRCHCLS5                ; Done
  444. SRCHCLS4: MOV     DI,OFFSET FILENAME            ; UnParse File Name
  445.           CALL    UNPARSE
  446.           CLC                                   ; Clear Error Flag
  447. SRCHCLS5: POP     SI                            ; Restore Registers
  448.           POP     DI
  449.           POP     CX
  450.           POP     AX
  451.           RET                                   ; Done
  452.  
  453. READCLST: PUSH    AX                            ; Save Registers
  454.           PUSH    CX
  455.           PUSH    DX
  456.           MOV     AX,BX                         ; Calculate Absolute Sector #
  457.           SUB     AX,2
  458.           MOV     CX,CLSTSEC
  459.           MUL     CX
  460.           ADD     AX,STARTSEC
  461.           MOV     DX,AX
  462.           MOV     AL,DRIVE
  463.           PUSH    BX                            ; Save Registers
  464.           PUSH    DI
  465.           MOV     BX,DI                         ; Read Cluster
  466.           INT     25H
  467.           POPF
  468.           POP     DI                            ; Restore Registers
  469.           POP     BX
  470.           CALL    NEXTCLST                      ; Get Next Cluster Number
  471.           MOV     AX,CLSTSEC                    ; Increment Buffer Pointer
  472.           MOV     CX,SECSIZE
  473.           MUL     CX
  474.           ADD     DI,AX
  475.           POP     DX                            ; Restore Registers
  476.           POP     CX
  477.           POP     AX
  478.           RET                                   ; Done
  479.  
  480. PREVCLST: PUSH    BX                            ; Save Registers
  481.           PUSH    CX
  482.           PUSH    DX
  483.           MOV     DX,BX                         ; Reserve Cluster Number
  484.           MOV     CX,CLSTTOT                    ; Start Looking at Last Cluster
  485. PREVCLS1: MOV     BX,CX                         ; Check Cluster
  486.           INC     BX
  487.           CALL    NEXTCLST
  488.           CMP     BX,DX                         ; If Match, Use It
  489.           LOOPNE  PREVCLS1                      ; Else Repeat
  490.           JNE     PREVCLS2                      ; If No Match, Return Zero
  491.           ADD     CX,2                          ; Adjust for Cluster Number
  492. PREVCLS2: MOV     AX,CX                         ; AX = Cluster Number
  493.           POP     DX                            ; Restore Registers
  494.           POP     CX
  495.           POP     BX
  496.           RET                                   ; Done
  497.  
  498. NEXTCLST: CMP     FATSIZE,3                     ; If FAT Size = 16 Bits,
  499.           JE      NEXTCLS1
  500.           SHL     BX,1                          ;   Simply Read Next Cluster #
  501.           MOV     BX,FATBUF[BX]
  502.           RET                                   ;   Done
  503. NEXTCLS1: PUSH    AX                            ; Save Registers
  504.           PUSH    CX
  505.           MOV     AX,BX                         ; Word # = Cluster # * 1.5
  506.           SHL     AX,1
  507.           ADD     BX,AX
  508.           SHR     BX,1
  509.           MOV     BX,FATBUF[BX]
  510.           JNC     NEXTCLS2                      ; If Odd, Use 12 MSB's
  511.           MOV     CL,4
  512.           SHR     BX,CL
  513. NEXTCLS2: AND     BX,0FFFH                      ; Else Use 12 LSB's
  514.           POP     CX                            ; Restore Registers
  515.           POP     AX
  516.           RET                                   ; Done
  517.  
  518. UNPARSE:  PUSH    CX                            ; Save Registers
  519.           PUSH    DI
  520.           PUSH    SI
  521.           MOV     CX,8                          ; FileName Length = 8 Max
  522. UNPARSE1: LODSB                                 ; Read Character
  523.           CMP     AL,' '                        ; If Space, Exit Loop
  524.           JE      UNPARSE2
  525.           STOSB                                 ; Move Character
  526.           LOOP    UNPARSE1                      ; Repeat
  527. UNPARSE2: MOV     AL,'.'                        ; Put a Dot in the String
  528.           STOSB
  529.           POP     SI                            ; Point to Extension
  530.           PUSH    SI
  531.           ADD     SI,8
  532.           MOV     CX,3                          ; Extension Length = 3 Max
  533. UNPARSE3: LODSB                                 ; Read Character
  534.           CMP     AL,' '                        ; If Space, Exit Loop
  535.           JE      UNPARSE4
  536.           STOSB                                 ; Move Character
  537.           LOOP    UNPARSE3                      ; Repeat
  538. UNPARSE4: CMP     CX,3                          ; If No Extension, Remove Dot
  539.           JNE     UNPARSE5
  540.           DEC     DI
  541. UNPARSE5: MOV     AL,0                          ; Terminate FileName
  542.           STOSB
  543.           MOV     AL,'$'
  544.           STOSB
  545.           POP     SI                            ; Restore Registers
  546.           POP     DI
  547.           POP     CX
  548.           RET                                   ; Done
  549.  
  550. MOVSTR:   LODSB                                 ; Read Source
  551.           STOSB                                 ; Write Destination
  552.           OR      AL,AL                         ; If Not EOS, Repeat
  553.           JNZ     MOVSTR
  554.           RET                                   ; Done
  555.  
  556. GET_WORD: PUSH    BX                            ; Save Register
  557.           XOR     DX,DX                         ; Value = 0
  558. GET_WRD1: LODSB                                 ; Read Character
  559.           CMP     AL,'0'                        ; If Not Numeric, Done
  560.           JB      GET_WRD2
  561.           CMP     AL,'9'
  562.           JA      GET_WRD2
  563.           SUB     AL,'0'                        ; Convert to BCD
  564.           CBW
  565.           MOV     BX,AX                         ; Value = Value*10+BCD
  566.           MOV     AX,10
  567.           MUL     DX
  568.           ADD     AX,BX
  569.           MOV     DX,AX
  570.           JMP     GET_WRD1                      ; Repeat
  571. GET_WRD2: DEC     SI
  572.           POP     BX                            ; Restore Register
  573.           RET                                   ; Done
  574.  
  575. STRIP0:   CMP     BYTE PTR [DI],'0'             ; If Character != '0', Done
  576.           JNE     STRIP1
  577.           CMP     BYTE PTR [DI+1],'0'           ; If Next Character != Digit,
  578.           JL      STRIP1                        ;   Done
  579.           CMP     BYTE PTR [DI+1],'9'
  580.           JG      STRIP1
  581.           MOV     BYTE PTR [DI],' '             ; Change '0' to ' '
  582.           INC     DI                            ; Point to Next Character
  583.           JMP     SHORT STRIP0                  ; Repeat
  584. STRIP1:   RET                                   ; Done
  585.  
  586. DEC2OUT:  PUSH    AX                            ; Save Registers
  587.           PUSH    BX
  588.           XOR     AH,AH                         ; Clear AH
  589.           MOV     BL,10                         ; AH=AX%10,AL=AX/10
  590.           DIV     BL
  591.           ADD     AX,'00'                       ; Convert to ASCII
  592.           SUB     DI,2
  593.           MOV     [DI],AX                       ; Store in String
  594.           POP     BX                            ; Restore Registers
  595.           POP     AX
  596.           RET                                   ; Done
  597.  
  598. DEC4OUT:  PUSH    AX                            ; Save Registers
  599.           PUSH    BX
  600.           MOV     BL,100                        ; AH=AX%100,AL=AX/100
  601.           DIV     BL
  602.           XCHG    AH,AL                         ; Convert 2 LSD's
  603.           CALL    DEC2OUT
  604.           XCHG    AH,AL                         ; Convert 2 MSD's
  605.           CALL    DEC2OUT
  606.           POP     BX                            ; Restore Registers
  607.           POP     AX
  608.           RET                                   ; Done
  609.  
  610. DEC5OUT:  PUSH    AX                            ; Save Registers
  611.           PUSH    BX
  612.           PUSH    DX                            ; DX=AX%10000,AX=AX/10000
  613.           MOV     BX,10000
  614.           XOR     DX,DX
  615.           DIV     BX
  616.           XCHG    DX,AX                         ; Convert 4 LSD's
  617.           CALL    DEC4OUT
  618.           XCHG    DX,AX                         ; Convert MSD
  619.           ADD     AL,'0'
  620.           SUB     DI,1
  621.           MOV     [DI],AL
  622.           POP     DX                            ; Restore Registers
  623.           POP     BX
  624.           POP     AX
  625.           RET                                   ; Done
  626.  
  627. FATBUF    LABEL   WORD
  628.  
  629. CODE      ENDS
  630.  
  631.           END     OWNER
  632.